"use strict";

var _ = require("underscore"),
    S = require("string"),
    path = require("path"),
    C = require('./../common.js'),
    Router = require('../router.js').Router;

module.exports = Router.extend({
    //instance members

    constructor: function(mount, webModule, req, res, info) {
        this.base(mount, webModule, req, res, info);

        this.params = [info.param];

        this.extend({
            handleError: function (error) {
                return Router.onError(webModule, req, res, error, true);
            }
        });
    }
}, {
    //static members

    mount: function(webModule, route, options, cb) {
        options = _.extend({
            hasModule: false,
            resourcePath: 'resources'
        }, options);

        var self = this;

        function createRouter(req, res, method, param, next) {
            try {
                var restInfo = {
                    action: method,
                    param: param
                }, nodes = [], modName, resourceName;

                if (options.hasModule) {
                    modName = S(req.params.module).camelize();
                    nodes.push(modName);
                    restInfo.moduleName = modName;
                }

                resourceName = S(req.params.resource).camelize();
                nodes.push(resourceName);

                var resourceRelPath = nodes.join('/');
                if (resourceRelPath.indexOf('..') >= 0) {
                    return Router.onError(webModule, req, res, C.HttpCode.HTTP_BAD_REQUEST);
                }

                restInfo.controllerPath = C.urlJoin(options.resourcePath, resourceRelPath);

                req.router = new self(route, webModule, req, res, restInfo);

                next();
            } catch (error) {
                Router.onError(webModule, req, res, error, true);
            }
        }

        var withoutId = function(req, res, next) {
            res.type('application/json');

            var method, reqMethod = req.method.toLowerCase(), param;

            if (reqMethod == 'get') {
                method = 'list';
                param = req.query;
            } else if (reqMethod == 'post') {
                method = 'create';
                param = req.body;
            } else {
                Router.onError(webModule, req, res, C.HttpCode.HTTP_METHOD_NOT_ALLOWED, true);
                return;
            }

            createRouter(req, res, method, param, next);

        }, withId = function(req, res, next) {
            res.type('application/json');

            var method, reqMethod = req.method.toLowerCase();

            switch (reqMethod) {
                case 'get':
                    method = 'detail';
                    break;

                case 'put':
                case 'post':
                    method = 'update';
                    break;

                case 'delete':
                    method = 'remove';
                    break;

                default:
                    Router.onError(webModule, req, res, C.HttpCode.HTTP_METHOD_NOT_ALLOWED, true);
                    return;
            }

            createRouter(req, res, method, req.params.id, next);
        };

        var r1, engine = webModule.app.engine;

        Router.getMiddlewares(webModule, route, options.middlewares, function (err, middlewares) {
            if (err) return cb(err);

            middlewares.push(Router.dispatch);

            if (options.hasModule) {
                r1 = C.urlJoin(route, '/:module/:resource');
            } else {
                r1 = C.urlJoin(route, '/:resource');
            }

            var withoutIdHandlers = [ withoutId ].concat(middlewares);

            engine.get(r1, withoutIdHandlers);
            engine.post(r1, withoutIdHandlers);

            var r2 = r1 + '/:id';
            var withIdHandlers = [ withId ].concat(middlewares);

            engine.post(r2, withIdHandlers);
            engine.get(r2, withIdHandlers);
            engine.put(r2, withIdHandlers);
            engine.delete(r2, withIdHandlers);

            cb();
        });
    }
});
